//
//  IM_Service.m
//  SportSocial
//
//  Created by yull on 14/12/9.
//  Copyright (c) 2014年 yull. All rights reserved.
//

#import "IM_Service.h"
#import "Reachability.h"
#import "IM_Service+Read.h"
#import "IM_Service+Write.h"
#import "IMNet.h"
#import "UserIMNet.h"
#import "UserNet.h"
#import "FriendIMNet.h"
#import "GroupIMNet.h"
#import "GroupSystemNet.h"
#import "PrivateIMNet.h"

static volatile int32_t im_bk_task_count;

@interface IM_Service () <GCDAsyncSocketDelegate>

@end

@implementation IM_Service

+ (IM_Service *)instance
{
    static IM_Service *service = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        service = [[IM_Service alloc] init];
    });
    return service;
}

- (instancetype)init
{
    if (self = [super init]) {
        self.strHost = nil;
        
        self.nPort = 0;
        
        [self initIMNet];
        
        self.serviceQueue = dispatch_queue_create("IMService.queue", NULL);
        
        self.asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:self.serviceQueue];
        
//        self.heartbeatTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.serviceQueue);
//        
//        dispatch_source_set_timer(self.heartbeatTimer,
//                                  dispatch_time(DISPATCH_TIME_NOW, HEART_TIME_INTERVAL * NSEC_PER_SEC),
//                                  HEART_TIME_INTERVAL * NSEC_PER_SEC, 0);
//        
//        dispatch_source_set_event_handler(self.heartbeatTimer, ^{
//            [self sendHeartBeat];
//        });
//        
//        dispatch_resume(self.heartbeatTimer);
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(appEnterForeground)
                                                     name:UIApplicationWillEnterForegroundNotification
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(appEnterBackground)
                                                     name:UIApplicationDidEnterBackgroundNotification
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(reachabilityChanged:)
                                                     name:kReachabilityChangedNotification
                                                   object:nil];
        
        
        self.buffData = [NSMutableData data];
        self.nTimeout = 60;
        
        self.status = IMServiceStatusOffline;
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)initIMNet
{
    self.arrayNet = [NSMutableArray arrayWithObjects:[UserIMNet shareInstance],
                     [FriendIMNet shareInstance],
                     [GroupIMNet shareInstance],
                     [PrivateIMNet shareInstance],
                     [GroupSystemNet shareInstance],nil];
}

#pragma mark -
#pragma mark GCDAsyncSocketDelegate

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    
    [self.asyncSocket readDataWithTimeout:-1 tag:0];
    
    [self.buffData appendData:data];
    
    [self parseBuffData];
}

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    
    NSLog(@"imservices didConnectToHost:%@ port:%d", host, port);
    
    [self resetRevBuffer];
    
    [self.asyncSocket readDataWithTimeout:-1 tag:0];
    
    if ([CurrentUser shareInstance].isLogin) {
        [[UserIMNet shareInstance] login];
        
        [UserNet updateIOSdeviceTokenSuccessBlock:^(AFHTTPRequestOperation *operation, id responseObject) {
            NSLog(@"devicetoken更新成功！");
        } failBlock:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"devicetoken更新失败！");
        }];
        
        self.heartbeatTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.serviceQueue);
        
        dispatch_source_set_timer(self.heartbeatTimer,
                                  dispatch_time(DISPATCH_TIME_NOW, HEART_TIME_INTERVAL * NSEC_PER_SEC),
                                  HEART_TIME_INTERVAL * NSEC_PER_SEC, 0);
        
        dispatch_source_set_event_handler(self.heartbeatTimer, ^{
            [self sendHeartBeat];
        });
        
        dispatch_resume(self.heartbeatTimer);
    }
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    NSLog(@"发包成功!");
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    NSLog(@"断开连接");
    if (self.heartbeatTimer) {
        dispatch_source_cancel(self.heartbeatTimer);
    }
    if ([FunctionMethod networkAvailable]) {
         [self connect];
    }
}

- (void)resetRevBuffer {
    
    self.buffData = [NSMutableData data];
}

- (void)prepare {
    [IMNet getIMServerWithSuccessBlock:^(AFHTTPRequestOperation *operation, id responseObject) {
        //NSLog(@"%@",[responseObject objectForKey:@"message"]);
        BOOL success = [[responseObject objectForKey:@"success"] boolValue];
        if (success) {
            NSDictionary *dataDic = [responseObject objectForKey:@"data"];
            self.strHost = [dataDic objectForKey:@"acceptClientDns"];
            self.nPort = [[dataDic objectForKey:@"acceptClientport"] integerValue];
            self.canConnect = YES;
            
            [self connect];
        } else {
            [self prepare];
        }
        
//        self.strHost = @"114.80.252.69";
//        self.nPort = 30000;
//        self.canConnect = YES;
//        
//        [self connect];
    } failBlock:^(AFHTTPRequestOperation *operation, NSError *error) {
        [self prepare];
    }];
}

- (void)connect {
    if ([self.asyncSocket isConnected]) {
        return;
    }
    
    self.status = IMServiceStatusConnecting;
    
    NSError *err = nil;
    
    if (!self.strHost ||
        self.nPort == 0) {
        
    }
    
    self.asyncSocket.delegate = self;
    
    BOOL result = [self.asyncSocket
                   connectToHost:self.strHost
                   onPort:self.nPort
                   withTimeout:self.nTimeout
                   error:&err];
    if (result) {
        NSLog(@"连接成功!");
    }else {
        NSLog(@"连接失败!");
    }
}

- (BOOL)isConnected {
    
    return [self.asyncSocket isConnected];
}

- (int)backgroundTaskCount {
    
    return im_bk_task_count;
}

- (void)disconnectService {
    dispatch_async(_serviceQueue, ^{
        if ([self.asyncSocket isConnected]) {
            
            NSLog(@"imservices disconnect");
            self.asyncSocket.delegate = nil;
            self.status = IMServiceStatusOffline;
            [self.asyncSocket disconnect];
            
            [self connect];
            im_bk_task_count = 0;
        }
    });
}

#pragma mark -
#pragma mark Private Notification

- (void)appEnterForeground {
    

}

- (void)appEnterBackground {
    
    
}

- (void)reachabilityChanged:(NSNotification *)note {
    
    Reachability *notifyReachability = [note object];
    
    if ([notifyReachability isReachable]) {
        
        dispatch_async(_serviceQueue, ^{
            
            self.asyncSocket.delegate = nil;
            
            [self.asyncSocket disconnect];
            
            [self connect];
        });
        
    } else {
        dispatch_async(_serviceQueue, ^{
            [self.asyncSocket disconnect];
        });
    }
}

@end
